from flask import current_app, jsonify,session
from flask import request, render_template, g, redirect
from info import user_login_data, db, constants
from info.models import Category, News, User
from info.utils.response_code import RET
from . import profile_bp
from info.utils.captcha.pic_storage import pic_storage


# 使用蓝图
# 127.0.0.1:5000/user/info
@profile_bp.route("/info")
@user_login_data
def user_info():
    """用户中心 后端接口"""
    """
    1.查询当前登陆用户
    """
    # 查询当前登陆用户
    user = g.user
    if not user:
        return redirect('/')
    # 返回数据的字典
    data = {
        "user": user.to_dict() if user else None
    }

    return render_template("profile/user.html", data=data)


# 127.0.0.1:5000/user/base_info
@profile_bp.route("/base_info", methods=['GET', 'POST'])
@user_login_data
def base_info():
    """展示/修改用户基本信息"""
    """
    0.判断请求方式: get请求页面,post提交数据
    1.获取参数
        user:当前登陆用户    nick_name:昵称    signature:个性签名    gender:性别
    2.参数校验
        2.1 非空判断
    3.逻辑处理
        3.1 修改用户对象属性
        3.2 保存回数据库
    4.返回结果
    """
    # 0.判断请求方式: get请求页面,post提交数据
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    if request.method == 'GET':
        data = {
            "user": user.to_dict() if user else None
        }
        return render_template("profile/user_base_info.html", data=data)
    # 1.获取参数
    nick_name = request.json.get("nick_name")
    signature = request.json.get("signature")
    gender = request.json.get("gender")
    # 2.参数校验
    if not all([nick_name, signature, gender]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")
    if gender not in ['MAN', 'WOMAN']:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    try:
        user_list = User.query.filter(User.nick_name == nick_name, User.id != user.id).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="用户昵称查询异常")
    if user_list:
        return jsonify(errno=RET.PARAMERR, errmsg="用户昵称已存在")
    # 3.1 修改用户对象属性
    user.nick_name = nick_name
    user.gender = gender
    user.signature = signature
    # 修改session中的用户数据
    session['nick_name'] = nick_name
    # 3.2 保存回数据库
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存用户信息异常")

    return jsonify(errno=RET.OK, errmsg="修改用户信息成功")


# 127.0.0.1:5000/user/pic_info
@profile_bp.route("/pic_info", methods=['GET', 'POST'])
@user_login_data
def pic_info():
    """展示/修改用户头像"""
    """
    0.判断请求方式: get请求页面,post提交数据
    1.获取参数
        avatar:图片文件
    2.参数校验
        2.1 非空判断
    3.逻辑处理
        3.1 将图片数据转化为二进制格式
        3.2 调用pic_storage工具将图片上传到七牛云,返回图片名称
        3.3 将图片名称保存到用户avatar_url上
        3.4 返回完整的url
    4.返回结果
    """
    # 0.判断请求方式: get请求页面,post提交数据
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    if request.method == 'GET':
        data = {
            "user": user.to_dict()
        }
        return render_template("profile/user_pic_info.html", data=data)
    # 1.获取参数
    avatar = request.files.get("avatar")
    # 2.参数校验
    if not avatar:
        return jsonify(errno=RET.PARAMERR, errmsg="请选择图片")
    # 3.1 将图片数据转化为二进制格式
    pic_data = avatar.read()
    # 3.2 将图片上传到七牛云,返回图片名称
    try:
        pic_name = pic_storage(pic_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg="上传头像失败")
    # 3.3 将图片名称保存到用户avatar_url上
    user.avatar_url = pic_name
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存用户图片数据异常")
    # 3.3 返回完整的url
    pic_url = constants.QINIU_DOMIN_PREFIX + pic_name
    data = {
        "pic_url": pic_url
    }

    return jsonify(errno=RET.OK, errmsg="修改用户头像成功", data=data)


# 127.0.0.1:5000/user/pass_info
@profile_bp.route("/pass_info", methods=['GET', 'POST'])
@user_login_data
def pass_info():
    """修改用户密码"""
    """
    0.判断请求方式: get请求页面,post提交数据
    1.获取参数
        old_password: 原密码  new_password: 新密码
    2.参数校验
        2.1 非空判断
    3.逻辑处理
        3.1 判断原密码和当前用户密码是否相同
        3.2 设置新密码,上传到数据库
    4.返回结果
    """
    # 0.判断请求方式: get请求页面,post提交数据
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    if request.method == 'GET':
        return render_template("profile/user_pass_info.html")
    # 1.获取参数
    old_password = request.json.get("old_password")
    new_password = request.json.get("new_password")
    # 2.参数校验
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")
    # 3.1 判断原密码和当前用户密码是否相同
    if not user.check_passowrd(old_password):
        return jsonify(errno=RET.PARAMERR, errmsg="密码错误")
    # 3.2 设置新密码,上传到数据库
    user.password = new_password
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存用户密码失败")
    return jsonify(errno=RET.OK, errmsg="修改密码成功")


# 127.0.0.1:5000/user/collection
@profile_bp.route("/collection")
@user_login_data
def user_collection():
    """用户新闻收藏"""
    """
    1.获取页数
    2.查询新闻数据
        1.1 对数据进行分页
        1.2 生成对象字典列表
    3.返回数据
    """
    # 0.判断用户是否登陆
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    # 1.获取页数
    p = request.args.get('p', 1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    # 2.查询新闻数据
    # current_page = 1
    # total_page = 1
    try:
        # 对收藏的新闻进行分页
        paginate = user.collection_news.paginate(p, constants.USER_COLLECTION_MAX_NEWS, False)
        # 获取分页数据
        collection_news = paginate.items
        # 获取当前页数
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询新闻数据异常")
    news_dict_list = []
    for news in collection_news:
        news_dict_list.append(news.to_review_dict())
    # 2.返回数据
    # 数据字典
    data = {
        "collections": news_dict_list,
        "current_page": current_page,
        "total_page": total_page
    }
    return render_template('profile/user_collection.html', data=data)


# 127.0.0.1:5000/user/user_follow
@profile_bp.route("/user_follow")
@user_login_data
def user_follow():
    """用户关注列表"""
    """
    1.获取页数
    2.查询关注数据
        1.1 对数据进行分页
        1.2 生成对象字典列表
    3.返回数据
    """
    # 0.判断用户是否登陆
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    # 1.获取页数
    p = request.args.get('p', 1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    # 2.查询新闻数据
    try:
        # 对收藏的新闻进行分页
        paginate = user.followed.paginate(p, constants.USER_FOLLOWED_MAX_COUNT, False)
        # 获取分页数据
        followed = paginate.items
        # 获取当前页数
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询用户关注数据异常")
    followed_dict_list = []
    for user in followed:
        followed_dict_list.append(user.to_dict())
    # 2.返回数据
    # 数据字典
    data = {
        "users": followed_dict_list,
        "current_page": current_page,
        "total_page": total_page
    }
    return render_template('profile/user_follow.html', data=data)


# 127.0.0.1:5000/user/news_release
@profile_bp.route("/news_release", methods=['GET', 'POST'])
@user_login_data
def news_release():
    """用户发布新闻"""
    """
    判断请求方式:
    1.get请求:返回页面
        1.1 获取分类数据
    """
    # 0.判断请求方式: get请求页面,post提交数据
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    if request.method == 'GET':
        # 1.1 获取分类数据
        try:
            categories = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="分类数据查询异常")
        category_list = []
        for category in categories:
            category_list.append(category.to_dict())
        # 移除`最新`分类
        category_list.pop(0)
        data = {
            "categories": category_list
        }
        return render_template("profile/user_news_release.html", data=data)
    """
    2.post:提交数据
        1.获取参数
            title:新闻标题    category_id:新闻分类_id    digest:新闻摘要
            index_image:索引图片    content:新闻内容
        2.参数校验
            2.1 非空判断
            2.2 读取图片并上传到七牛云
        3.逻辑处理
            3.1 创建new对象,并设置对应属性
            3.2 将news对象保存到数据库
        4.返回结果
    """
    # 1.获取参数
    title = request.form.get("title")
    category_id = request.form.get("category")
    digest = request.form.get("digest")
    # 注意:图片从files中提取
    index_image = request.files.get("index_image")
    content = request.form.get("content")
    # 2.1 非空判断
    if not all([title, category_id, digest, index_image, content]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")
    # 2.2 读取图片并上传到七牛云
    try:
        pic_data = index_image.read()
        key = pic_storage(pic_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="图片数据有误")
    # 3.1 创建news对象,并设置对应属性
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + key
    news.content = content
    news.user_id = user.id
    news.source = "个人发布"
    # 1代表待审核状态
    news.status = 1
    # 3.2 将news对象保存到数据库
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存新闻对象异常")

    return jsonify(errno=RET.OK, errmsg="发布成功, 等待审核")


# 127.0.0.1:5000/user/news_list
@profile_bp.route("/news_list")
@user_login_data
def news_list():
    """用户新闻列表展示"""
    """
    1.获取页数
    2.查询新闻数据
        1.1 对数据进行分页
        1.2 生成对象字典列表
    3.返回数据
    """
    # 0.判断用户是否登陆
    user = g.user
    if not user:
        current_app.logger.error("用户未登录")
        return redirect('/')
    # 1.获取页数
    p = request.args.get('p', 1)
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    # 2.查询新闻数据
    try:
        # 对收藏的新闻进行分页
        paginate = News.query.filter(News.user_id == user.id).paginate(p, constants.USER_COLLECTION_MAX_NEWS, False)
        # 获取分页数据
        collection_news = paginate.items
        # 获取当前页数
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询新闻数据异常")
    news_dict_list = []
    for news in collection_news:
        news_dict_list.append(news.to_review_dict())
    # 2.返回数据
    # 数据字典
    data = {
        "news_list": news_dict_list,
        "current_page": current_page,
        "total_page": total_page
    }
    return render_template('profile/user_news_list.html', data=data)





